#include "jf_aod_gpu.h"
#include "opencv2/cudabgsegm.hpp"
#include "opencv2/cudafilters.hpp"
#include <opencv2/core/opengl.hpp>
#include "opencv2/core/cuda.hpp"
#include <opencv2/cudaarithm.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudawarping.hpp>
#include <assert.h>
#include <queue>
#include <unordered_map>


using GpuMat = cv::cuda::GpuMat;

string gettime(){
    time_t t = time(0);
    char ch[64];
    strftime(ch, sizeof(ch), "%Y-%m-%d %H:%M:%S", localtime(&t)); //年-月-日 时：分：秒
    string str_time(ch);
    return str_time;
}

//用于追踪起始位置
struct AODTrack{
    Point center;
    int frameCount = 0; //已经出现的帧数
    int discontinuousCounts = 0; //目前不连续的帧数
    bool isContinuous = true;

};

struct AODAlarmTime{
    Point center;
    double startTime;
};

struct AODFrequency{
    Point center;
    bool isContinuous = false;
    vector<cv::Rect> detectedRect;
    int count = 0;
    int discontinuousTimes = 0;
};//面积变化规律策略中使用的struct



class AODGpuPrivate:public AbandonObjectDetect{
    public:
        Ptr<BackgroundSubtractor> fgbgl;
        Ptr<BackgroundSubtractor> fgbgs;
        Ptr<BackgroundSubtractor> bg;
        GpuMat BL;
        GpuMat BS;
        // cv::Rect roi;
        int nAreaThresholdMin_ = 30;
        int nAreaThresholdMax_ = 20000;
        GpuMat back;
        GpuMat fore;
        GpuMat backz;
        GpuMat sub;
        GpuMat static_obj_map;
        int detectFlag = 0;
        // Ptr<cuda::Filter> erode_s3 = cuda::createMorphologyFilter(MORPH_ERODE, CV_8UC3, getStructuringElement(MORPH_RECT, Size(5, 5)));
        // Ptr<cuda::Filter> open_s5 = cuda::createMorphologyFilter(MORPH_ERODE, CV_8UC3, getStructuringElement(MORPH_RECT, Size(5, 5)));
        int longBackgroundInterval = 20;
        int shortBackgroundINterval = 1;
        int clfg = longBackgroundInterval;
        int csfg = shortBackgroundINterval;
        // self.L = np.zeros(np.shape(background)[0:2])
        GpuMat L;
        // static obj likelihood constants
        int k = 7, maxe = 2000, thh = 800;

        // obj-extraction constants
        int slidewindowtime = 0;
        int th_sp = 200; //a th for number of static pixels, default 20**2
        // self.static_objs = []
        GpuMat getForegroundMask(GpuMat frame, GpuMat background, int th);

        Ptr<BackgroundSubtractor> MOG2init(int history, int T, int nMixtures);
        vector<Rect> get_abandoned_objs(GpuMat frame);
        vector<cv::Rect> extract_objs2(GpuMat im, int area);
        
        void valTransform(const GpuMat& image, GpuMat& outImage, float div);
        vector<cv::Rect> static_objs;
        GpuMat clean_map();
        vector<cv::Rect> extract_objs3(GpuMat im);
        int recordTime = 0;
        int nowTime = 0;
        // int AreaThresholdMin = 40;
        // int AreaThresholdMax = 10000;
        vector<AODTrack> track_vec;
       
        Point getCenterPoint(Rect rect);
        int count = 0;
        int step = 3;
        int accurate = 30;
        queue<GpuMat> q_back;
        vector<cv::Rect> detectedRect;
        vector<AODAlarmTime> alarmVec;
        vector<AODFrequency> af_vec;
        bool isUseAlarmTimeTactic = true;
        int freCount = 50; 
        int maxDiscontinuedTimes = 2;
        int interval = 3000; //每interval帧更新一次背景
        void cleanAODFrequency();
        void addAODFrequency(cv::Rect rt);
        void detectPreparedRect();
        int threscount = 100;
        int degree = 90;
        int detectLeftFilter(GpuMat& frame, Rect& rect);
        double GetGrayAvg(GpuMat src);  
        bool isAllowedRange(Point p_center, Point p);
        vector<Rect> preparedRect;
        int detectLeftRemove(GpuMat& mat, Rect& rect);
        Rect scale_rect(const Rect& r, float scale);
        int getmaxDiscontinuedTimes();
        bool getUseAlarmTimeTactic();
        // vector<AODAlarmTime> alarmVec;
        float fTimeGapThreshold_ = 120.f;
        float getTimeGapThreshold();

        void trackDetectedRect(const cv::Rect detectedRect);
        void clearTrackRect();
        int getDetectedFrameCounts(const cv::Rect detectedRect);
        int skipNum = 1;

    public:
        int gpu_id;
        AODGpuPrivate(){
            this->gpu_id = 0;   // use gpu_id=0 by default
        };
        AODGpuPrivate(int gpu_id){
            this->gpu_id = gpu_id;
        };
};

AODGpu::AODGpu():m_pHandle(new AODGpuPrivate()){
    init();
};

AODGpu::AODGpu(int gpu_id):m_pHandle(new AODGpuPrivate(gpu_id)){
    init();
};

AODGpu::~AODGpu () {};

void AODGpu::init() {
    setDevice(m_pHandle->gpu_id);
    // m_pHandle->allocator_ = new GPUAllocator(1024 * 1024 * 128);
    // m_pHandle->fgbgl = m_pHandle->MOG2init(300, 25, 3);
    // m_pHandle->fgbgs = m_pHandle->MOG2init(300, 25, 3);
    m_pHandle->bg = m_pHandle->MOG2init(300, 25, 3);
    // m_pHandle->L.upload(cv::Mat::zeros(360, 480, CV_8UC1));
    cout<<"initial process finished"<<endl;
}

void AODGpu::detect(const AODInput &input){
        // GpuMat img(input.mat, m_pHandle->allocator_);
        // GpuMat img(host_img, m_pHandle->allocator_);
        GpuMat gmat(input.mat);
        if(getROI().area() > 0) {
            gmat = gmat(getROI()).clone();
        }
/*        if(getROI().area() > 0)
            gmat = input.mat(getROI()).clone();
        else gmat = input.mat.clone();*/

        GpuMat img(gmat);
        // GpuMat img = mat;
        cuda::resize(img, img, cv::Size(480, 320));
        vector<Rect> detectedRect = m_pHandle->extract_objs3(img);
        if(detectedRect.size() > 0){
            cv::Mat cpu_mat(img);
            AODOutput output;
            output.mat = cpu_mat;
            for(int i = 0; i < detectedRect.size(); i++){
                AODResult result;
                result.rt = detectedRect[i];
                result.type = 1;
                result.prop = 1;
                result.detectedFrameCounts = m_pHandle->getDetectedFrameCounts(detectedRect[i]);
                output.arrRes.push_back(result);
            }
            // this->cb_(AODOutput);
            this->cb_(output);
        }
}

void AODGpu::setAreaThresholdMin(int minArea){
    m_pHandle->nAreaThresholdMin_ = minArea;
}

void AODGpu::setAreaThresholdMax(int maxArea){
    m_pHandle->nAreaThresholdMax_ = maxArea;
}

GpuMat AODGpuPrivate::getForegroundMask(GpuMat frame, GpuMat background, int th){
    cv::Ptr<cv::cuda::Filter> gauss = cv::cuda::createGaussianFilter(frame.type(), -1, cv::Size(5, 5), 1);
    gauss->apply(frame, frame);
    GpuMat fgmask;
    cv::cuda::absdiff(frame, background, fgmask);
    // if(fgmask.channels() == 3)
    cv::cuda::cvtColor(fgmask, fgmask, COLOR_BGR2GRAY);   // 从mat转来的gpu_mat没有alpha通道
    cuda::threshold(fgmask, fgmask, th, 255, THRESH_BINARY);
    Ptr<cuda::Filter> close_cal = cuda::createMorphologyFilter(MORPH_CLOSE, fgmask.type(), getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
    close_cal->apply(fgmask, fgmask);
    return fgmask;
}

Ptr<BackgroundSubtractor> AODGpuPrivate::MOG2init(int history, int T, int nMixtures){
    Ptr<BackgroundSubtractor> fgbg = 
        cuda::createBackgroundSubtractorMOG2(history, T, nMixtures);
    return fgbg;
}

vector<Rect> AODGpuPrivate::get_abandoned_objs(GpuMat frame){

    if(this->clfg == this->longBackgroundInterval){
        GpuMat frameL = frame.clone();
        GpuMat fgmask;
        this->fgbgl->apply(frameL, fgmask);
        this->fgbgl->getBackgroundImage(this->BL);
        // self.BL = self.fgbgl.getBackgroundImage(frameL)
        this->clfg = 0;
    }else{
        this->clfg += 1;
    }

    if(this->csfg == this->shortBackgroundINterval){
        GpuMat frameS = frame.clone();
        GpuMat fgmask;
        this->fgbgs->apply(frameS, fgmask);
        this->fgbgs->getBackgroundImage(this->BS);
        // self.BL = self.fgbgl.getBackgroundImage(frameL)
        this->csfg = 0;
    }else{
        this->csfg += 1;
    }
    
    GpuMat FL = getForegroundMask(frame, this->BL, 70);
    GpuMat FS = getForegroundMask(frame, this->BS, 70);

    GpuMat n_FS;
    cuda::bitwise_not(FS, n_FS);
    GpuMat static_obj;
    cuda::bitwise_and(FL, n_FS, static_obj);

    // Ptr<cuda::Filter> erode = cuda::createMorphologyFilter(MORPH_ERODE, CV_8UC3, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
    Ptr<cuda::Filter> close_cal = cuda::createMorphologyFilter(MORPH_CLOSE, static_obj.type(), getStructuringElement(MORPH_RECT, Size(3, 3)));
    close_cal->apply(static_obj, static_obj);

    GpuMat not_static;
    GpuMat n_FL;
    cuda::bitwise_not(FL, n_FL);
    cuda::bitwise_or(FL, n_FL, not_static);
    close_cal->apply(not_static, not_static);

    // FL&n_FS;
    GpuMat trans;
    cuda::threshold(static_obj, trans, 254, 1, THRESH_BINARY);
    GpuMat one_all(cv::Mat::ones(this->L.rows, this->L.cols, this->L.type()));
    GpuMat sum_;
    cuda::add(this->L, one_all, sum_);
    GpuMat and_;
    cuda::bitwise_and(this->L, one_all, and_);
    
    // trans*ones_all + trans_
    GpuMat mul1_;
    cuda::multiply(trans, sum_, mul1_);
 
    GpuMat mul2_;
    cuda::multiply(and_, this->L, mul2_);
    cuda::add(mul1_, mul2_, this->L);
    cuda::threshold(not_static, trans, 254, 1, THRESH_BINARY);

    cv::Mat k_all = cv::Mat::ones(this->L.rows, this->L.cols, this->L.type());
    k_all = k_all*this->k;
    // cuda::GpuMat one_all(mat);
    GpuMat gk_all(k_all);
    GpuMat sub_;
    cuda::subtract(this->L, gk_all, sub_);
    cuda::multiply(sub_, trans, mul1_);
    cuda::bitwise_and(trans, one_all, and_);
    cuda::multiply(this->L, and_, mul2_);
    cuda::add(mul1_, mul2_, this->L);
    cuda::threshold(this->L, this->L, this->maxe, this->maxe, THRESH_BINARY);
    cuda::threshold(this->L, this->static_obj_map, this->thh, 255, THRESH_BINARY);

    if(cuda::countNonZero(this->clean_map()) > this->th_sp){
        if(this->slidewindowtime > 200){
            vector<Rect> new_objs = this->extract_objs2(clean_map(), 25);
            //vector<Rect> new_objs;
            if(!new_objs.empty()){
                for(int i = 0; i < new_objs.size(); i++){
                    this->static_objs.push_back(new_objs[i]);
                }
            }
            this->slidewindowtime = 0;
        }else this->slidewindowtime +=1;
    }else{
        if(this->slidewindowtime < 0){
            this->slidewindowtime = 0;
        }else this->slidewindowtime -= 1;
    }

    vector<Rect>::iterator it;
    for(it=this->static_objs.begin();it!=this->static_objs.end();)
    {

        if((*it).area() > 0){
            int w = (*it).width;
            int h = (*it).height;
            if(cuda::countNonZero(this->static_obj_map(*it)) < w*h*0.05){
                this->static_objs.erase(it);
            }else{
                it++;
            }
        }   
    }
    return this->static_objs;
}


GpuMat AODGpuPrivate::clean_map(){
    GpuMat obj_map;
    // this->static_obj_map.download(obj_map);
    obj_map = this->static_obj_map;
    for(int i = 0; i < this->static_objs.size(); i++){
        obj_map(static_objs[i]).setTo(Scalar::all(0));
    }
    // this->static_obj_map.upload(obj_map);
    return obj_map;
}

vector<cv::Rect> AODGpuPrivate::extract_objs2(GpuMat im, int area){
    // kernel = cv::getStructuringElement(MORPH_ELLIPSE,(10,10));
    //  _, th = cv2.threshold(arr,127,255,0)
    Ptr<cuda::Filter> dilate_cal = cuda::createMorphologyFilter(MORPH_DILATE, im.type(), getStructuringElement(MORPH_RECT, Size(10, 10)));
    dilate_cal->apply(im, im);
    GpuMat th;
    cuda::threshold(im, th, 70, 255, THRESH_BINARY);
    cv::Mat mat;
    th.download(mat);
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    //_, th = cv2.threshold(arr,127,255,0)
    findContours(mat, contours, hierarchy, CV_RETR_TREE,  CV_CHAIN_APPROX_SIMPLE);
    vector<cv::Rect> rt_vec;
    
    for(int i=0;i<contours.size();i++)
    {
        cv::Rect rt = boundingRect(contours[i]);
        if(rt.area() > area) rt_vec.push_back(rt);
        
    }
    return rt_vec;
}

vector<cv::Rect> AODGpuPrivate::extract_objs3(GpuMat im){
    // kernel = cv::getStructuringElement(MORPH_ELLIPSE,(10,10));
    // _, th = cv2.threshold(arr,127,255,0)
    GpuMat frame = im;
    vector<vector<Point>> subcontours;
    cuda::cvtColor(frame, frame, COLOR_BGR2GRAY);   // 从mat转来的gpu_mat没有alpha通道
    if(this->count % this->step == 0){
        this->q_back.push(frame);
        if(this->q_back.size() > (this->accurate)) 
            this->q_back.pop();
    }

    this->bg->apply(frame, this->fore);
    this->bg->getBackgroundImage(this->back);

    // cv::erode(m_pHandle->back, m_pHandle->back, cv::Mat());//to remove image noise
    Ptr<cuda::Filter> erode_handle = cuda::createMorphologyFilter(MORPH_ERODE, this->back.type(), getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
    Ptr<cuda::Filter> dilate_handle = cuda::createMorphologyFilter(MORPH_DILATE, this->back.type(), getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
    erode_handle->apply(this->back, this->back);

    if (this->detectFlag == 0)
    {
        cuda::absdiff(this->back, this->back, this->backz);
        this->detectFlag = 10;
    }

    if(this->detectFlag == 10 && this->count > (this->threscount))//this loop runs once
    {
        this->backz = this->back.clone();//extra loop run to ensure stable initial background
        this->detectFlag = 20;
        // this->recordTime = getTickCount() / getTickFrequency();
        this->recordTime = 0;
        cout<<"Abandoned object detect begin ..."<<endl;
    }

    if(this->detectFlag == 20 && this->recordTime >= this->interval){
        cout << "New Interval of Abandoned Object Detection \n";
        this->backz = this->back.clone();//not backz=back as they'll become pointers pointing to same address
        // this->recordTime  = getTickCount() / (getTickFrequency());
        this->recordTime = 0;
    }

    if (this->detectFlag == 20)//interval can vary from 0 to 10 minutes; infinite loop
    {
        // cout << "New Interval of Abandoned Object Detection \n";
        this->recordTime++;
        if(this->detectedRect.size() > 0) this->detectedRect.clear();
        // this->backz = this->back.clone();//not backz=back as they'll become pointers pointing to same address

        cuda::absdiff(this->back, this->backz, this->sub);
		cuda::threshold(this->sub, this->sub, this->degree, 255, THRESH_BINARY);            

        erode_handle->apply(this->sub, this->sub);
        dilate_handle->apply(this->sub, this->sub);
        cv::Mat sub_(this->sub);
        findContours(sub_, subcontours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
        vector<Rect> subBoundRect(subcontours.size());
		// vector<Point> subcenter(subBoundRect.size());
		if(this->count % this->step == 0){
			this->q_back.push(frame);
			if(this->q_back.size() > this->accurate) this->q_back.pop();
		}

        int type;	
        for (int i = 0; i < subcontours.size(); i++) {
            //面积判断
            if(boundingRect(subcontours[i]).area() >= nAreaThresholdMin_ && boundingRect(subcontours[i]).area() <= nAreaThresholdMax_){
                subBoundRect[i] = boundingRect(subcontours[i]);	
                trackDetectedRect(subBoundRect[i]);
                this->addAODFrequency(subBoundRect[i]);
				this->detectPreparedRect();
			    this->cleanAODFrequency();
                //trackDetectedRect(subBoundRect[i]);
            }
        }
        for(int i = 0; i < this->preparedRect.size(); i++){
            if(!this->q_back.empty()){
                type = detectLeftFilter(frame, this->preparedRect[i]);
            }	
            else type = 1;
            if(type == 2) {
                this->detectedRect.push_back(this->preparedRect[i]); 				
            }
        }

        this->preparedRect.clear();

        vector<AODAlarmTime>::iterator it;
        double time_ = getTickCount()/getTickFrequency();

        for(it = this->alarmVec.begin();it !=this->alarmVec.end();)
        {
            if((time_ - (*it).startTime) > getTimeGapThreshold()){
                it = this->alarmVec.erase(it);
            }else it++;
        }

        for(int i = 0; i < this->detectedRect.size(); i++){
            int flag = 0;  //标记是不是找到了
            for(int j = 0; j < this->alarmVec.size(); j++){
                if(isAllowedRange(this->alarmVec[j].center, getCenterPoint(this->detectedRect[i]))){
                    //如果找到
                    vector<cv::Rect>::iterator it = this->detectedRect.begin() + i;
                    this->detectedRect.erase(it);
                    i--;
                    flag = 1;
                    break;	 
                }
            }
            if(flag == 0){//没找到
                AODAlarmTime al;
                al.center = getCenterPoint(this->detectedRect[i]);
                al.startTime = getTickCount() / getTickFrequency();
                this->alarmVec.push_back(al);
            }	
        }
        clearTrackRect();

    }


    this->count++;
    if(this->count == 1000000) this->count = 0;
    return this->detectedRect;
}

bool AODGpuPrivate::isAllowedRange(Point p_center, Point p){
	if(abs(p_center.x - p.x) <= 3 && abs(p_center.y - p.y) <=3){
		return true;
	}
	return false;
}

//追踪检测框起始帧
void AODGpuPrivate::trackDetectedRect(const cv::Rect detectedRect){
    vector<AODTrack>::iterator it;
    bool isContains = false;
    for(it = this->track_vec.begin(); it!= this->track_vec.end();){
        if(detectedRect.contains(it->center)){
        if(it->isContinuous) break;
        else{				
            it->frameCount++;
            it->isContinuous = true;
            isContains = true;
            break;
        }
        }
        it++;
    }
    if(!isContains){
    AODTrack at;
    at.center = getCenterPoint(detectedRect);
    at.frameCount++;
    this->track_vec.push_back(at);
    }
}

//获取rect中心点
Point AODGpuPrivate::getCenterPoint(Rect rect)
{
	Point cpt;
	cpt.x = rect.x + cvRound(rect.width / 2.0);
	cpt.y = rect.y + cvRound(rect.height / 2.0);
	return cpt;
}

//检测区域与过去一段时间的帧的检测区域的像素平均值比对
int AODGpuPrivate::detectLeftFilter(GpuMat& frame, Rect& rect)
{
	int returnVal = -1;
	queue<GpuMat> q = q_back;
	while(!q.empty()){
		GpuMat background = q.front();
        double avg1 = GetGrayAvg(background(rect));
        double avg2 = GetGrayAvg(frame(rect));
		if (abs(avg1 - avg2) > 2)
			return 1;
		q.pop();
	}
	// if(getUseAreaComparison() == false) return 2;
	// else return detectLeftRemove(frame, rect);
    return detectLeftRemove(frame, rect);
}

//与检测框周边的像素平均值进行比对
int AODGpuPrivate::detectLeftRemove(GpuMat& mat, Rect& rect)
{
	int returnVal = -1;
    cv::Mat background(mat);
	Rect surroundRect = scale_rect(rect, 4.f);
	if (surroundRect.width + surroundRect.x > background.cols) surroundRect.width = background.cols - surroundRect.x;
	if (surroundRect.height + surroundRect.y > background.rows) surroundRect.height = background.rows - surroundRect.y;
	Scalar S1 = mean(background(rect));
	Scalar S2 = mean(background(surroundRect));
	double dist1 = norm(S1);
	double dist2 = norm(S2);
	double ratio = 0.0;
	if (dist1 >= dist2)
		ratio = dist2 / dist1;
	else
		ratio = dist1 / dist2;

	if (ratio >= 0.9 && ratio <= 1.0)   returnVal = 1;
	else returnVal = 2;
	return returnVal;
}

double AODGpuPrivate::GetGrayAvg(GpuMat src)
{
    cv::Mat img(src);
    //cv::mean(src);
    return mean(img)[0]; 
}

bool AODGpuPrivate::getUseAlarmTimeTactic(){
	return this->isUseAlarmTimeTactic;
}


//得到的检测框加入面积变化检测序列
void AODGpuPrivate::addAODFrequency(cv::Rect rt){
	bool includeFlag = false;	
	for(int i = 0; i < this->af_vec.size(); i++){
		if(rt.contains(this->af_vec[i].center)){ //如果拥有
			this->af_vec[i].detectedRect.push_back(rt);
			this->af_vec[i].isContinuous = true;
			this->af_vec[i].count++;
			includeFlag = true;
			break;
		}
	}
	if(!includeFlag){
		AODFrequency aodFre;
		aodFre.detectedRect.push_back(rt);
		aodFre.center = getCenterPoint(rt);
		aodFre.isContinuous = true;
		aodFre.count++;
		this->af_vec.push_back(aodFre);
	}
}

void AODGpuPrivate::detectPreparedRect(){
	int nBIN = 5;
	for(int i = 0; i < this->af_vec.size(); i++){
		if(this->af_vec[i].count == this->freCount){
			vector<cv::Rect> arrInput = this->af_vec[i].detectedRect;
			auto fn = [](cv::Rect input1, cv::Rect input2) {
      			return input1.area() < input2.area();
   			};
			// 得到最大值/最小值
			auto max_iter = max_element(std::begin(arrInput), std::end(arrInput), fn);
			auto min_iter = min_element(std::begin(arrInput), std::end(arrInput), fn);
			auto max = *max_iter;
			auto min = *min_iter;
			int nHistSize = (max.area() - min.area()) / nBIN;
			// 最大值/最小值相同，说明面积变化平稳，可以断定这个检测框是可用的
   			 if (nHistSize == 0) {
				this->preparedRect.push_back(arrInput[arrInput.size()-1]);
				continue;
			}
			std::vector<int> arrHist;			
			for (auto &num : arrInput) {
				auto hist = (num.area() - min.area()) / nHistSize;
				arrHist.push_back(hist);
			}
			//直方图
			std::unordered_map<int, int> hash_table;
			for (auto &i : arrHist) {
				hash_table[i]++;
			}
			int max_freq = -1, most_freq_val = -1; // Initialize these values to -1
			int pre;
			bool flag = false;
			for(int i = 0; i < hash_table.size(); i++){
				if(i == 0) {
					flag = true;
					pre = hash_table[i];
				}	
				else {
					if(hash_table[i] - pre > 2){
						flag = false;
						break;
					}else pre = hash_table[i];
				}
			}
			if(flag == true){
				this->preparedRect.push_back(arrInput[arrInput.size()-1]);
			}

		}
	}
}

//清除面积检测序列中不时间连续或超过检测的次数范围的检测框
void AODGpuPrivate::cleanAODFrequency(){
	vector<AODFrequency>::iterator it;
	for(it = this->af_vec.begin();it != this->af_vec.end();)
     {
         if(!(*it).isContinuous){
			 (*it).discontinuousTimes++;
		 }else (*it).discontinuousTimes = 0;

		 if((*it).discontinuousTimes >= this->getmaxDiscontinuedTimes() || (*it).count == this->freCount)
             it= this->af_vec.erase(it);    //删除元素，返回值指向已删除元素的下一个位置    
         else{
			 (*it).isContinuous = false;
			 ++it; 
		 }
     }
}

int AODGpuPrivate::getmaxDiscontinuedTimes(){
	 return this->maxDiscontinuedTimes;
}

Rect AODGpuPrivate::scale_rect(const Rect& r, float scale)
{
	Point m = getCenterPoint(r);
	float width = r.width  * scale;
	float height = r.height * scale;
	int x = cvRound(m.x - width / 2);
	int y = cvRound(m.y - height / 2);
	if (x < 0) x = 0;
	if (y < 0) y = 0;
	return Rect(x, y, cvRound(width), cvRound(height));
}

void AODGpu::setTimeGapThreshold(float fSec){
    m_pHandle->fTimeGapThreshold_ = fSec;
}

float AODGpuPrivate::getTimeGapThreshold(){
    return this->fTimeGapThreshold_; 
}

//清理无效检测狂
void AODGpuPrivate::clearTrackRect(){
    vector<AODTrack>::iterator it;
    for(it = this->track_vec.begin(); it!= this->track_vec.end();){
        //如果检测框是时间连续的
        if(it->isContinuous){
        it->discontinuousCounts = 0;
        it->isContinuous = false; 
        it++;
        }else{
            //如果不是时间上连续的则不连续次数加1
            it->discontinuousCounts++;
            //不连续的次数达到50
            if(it->discontinuousCounts >= 10000){
                it = this->track_vec.erase(it);
            }else{//未达到50,则起始帧数加1
            it->frameCount++;
            it++;
            }
        }
    }
 }

//获取检测用了多少帧
int AODGpuPrivate::getDetectedFrameCounts(const cv::Rect detectedRect){
    int detectedFrameCount = 0;
    vector<AODTrack>::iterator it;
    for(it = this->track_vec.begin(); it!= this->track_vec.end();){
    if(detectedRect.contains(it->center)){
        detectedFrameCount = it->frameCount;
        this->track_vec.erase(it);
        break;
    }
    it++;
    }
    return detectedFrameCount;
}


void AODGpu::setinterval(int interval){
    m_pHandle->interval = interval;
}

//设置初始化帧数
void AODGpu::setthrescount(int threscount){
    m_pHandle->threscount = threscount;
}

//设置与过去每隔step帧取多少帧进行检测框比对
void AODGpu::setcomparedFrame(int num){
     m_pHandle->accurate = num;
}
//设置每隔step帧比对一次
void AODGpu::setstep(int step){
    m_pHandle->step = step;
}

 void AODGpu::setSensitivity(int degree){
    m_pHandle->degree = degree;
 }



